package com.agent.commons.ws;

import com.agent.commons.Result.NoticeResult;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint("/notice/{userId}")
@Component
@Slf4j
public class NoticeWebsocket {
    /**
     * 存放所有连接的会话session
     */
    public static Map<String, Session> clients=new ConcurrentHashMap<>();
    /**
     * userId关联sid（解决同一用户id，在多个web端连接的问题）
     */
    public static Map<String, Set<String>> conns = new ConcurrentHashMap<>();
    /**
     * 每个连接会话唯一的session标识
     */
    private String sid;

    /**
     * ws连接成功调用方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId){
        //生成sid
        this.sid = UUID.randomUUID().toString();
        clients.put(sid,session);
        //获取该用户建立的所有连接
        Set<String> sids = conns.get(userId);
        //如果为空则创建一个
        if(sids==null){
            //线程安全集合
            sids = conns.computeIfAbsent(userId, k -> ConcurrentHashMap.newKeySet());
            sids.add(sid);
        }else{
            //不为空则添加进集合中
            sids.add(sid);
        }
        conns.put(userId,sids);
        log.info("{}连接成功！",sid);
    }

    /**
     * ws连接关闭时
     */
    @OnClose
    public void onClose(){
        log.info("{}连接关闭！",sid);
        //断开连接
        conns.forEach((key, value) -> value.remove(this.sid));
        //清楚连接null的用户
        conns.entrySet().removeIf(entry -> entry.getValue().isEmpty());
        clients.remove(sid);
    }


    /**
     * 发送消息到对应用户连接session
     * @param userId
     * @param noticeResult
     */
    public static void sendMessageByUserId(String userId, NoticeResult<?> noticeResult){
        //对userId是否为null的校验
        if(!StringUtils.isEmpty(userId)){
            //把发送对象转换成json
            String message = JSON.toJSONString(noticeResult);
            //根据发送id，获取到该用户对应的连接session
            Set<String> sids = conns.get(userId);
            //采用迭代器遍历的方式
            for (String sid : sids) {
                if(sid==null) {
                    log.error("有sid为null！");
                }
                Session session = clients.get(sid);
                if (session != null) {
                    try {
                        session.getBasicRemote().sendText(message);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
}
